//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.UIDesigner.Monitor
{
    using System.Configuration;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.Commands;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.WpfComposite;
    using Microsoft.Practices.Unity;

    /// <summary>
    /// Initializes the monitor features and binds the veiws to the trident main window
    /// </summary>
    public class MonitorModule : IModule
    {
        /// <summary>
        /// Instnance of the Unity container
        /// </summary>
        private IUnityContainer container;

        /// <summary>
        /// Instance of the region manager
        /// </summary>
        private IRegionManager regionManager;

        /// <summary>
        /// Holds Monitor service
        /// </summary>
        private IMonitorService monitorService;

        /// <summary>
        /// Data product service.
        /// </summary>
        private IDataProductService dataProductService;

        /// <summary>
        /// Monitor setting service.
        /// </summary>
        private MonitorSettingService monitorSettingService;

        /// <summary>
        /// Monitor Logging Service.
        /// </summary>
        private MonitorLoggingService monitorLoggingService;

        /// <summary>
        /// Data product presentation model.
        /// </summary>
        private DataProductPresentationModel dataProductPresentationModel;

        /// <summary>
        /// ProcessingStatusPresentationModel.
        /// </summary>
        private ProcessingStatusPresentationModel processingStatusPresentationModel;

        /// <summary>
        /// InputOutputPresentationModel.
        /// </summary>
        private InputOutputPresentationModel inputOutputPresentationModel;

        /// <summary>
        /// PerformancePresentationModel.
        /// </summary>
        private PerformancePresentationModel performancePresentationModel;

        /// <summary>
        /// ExecutionVizualizerPresentationModel.
        /// </summary>
        private ExecutionVisualizerPresentationModel executionVisualizerPresentationModel;

        /// <summary>
        /// MonitorSettingsWindow.
        /// </summary>
        private MonitorSettingsWindow monitorSettingsWindow;

        /// <summary>
        /// WorkflowParametersPresentationModel.
        /// </summary>
        private WorkflowParametersPresentationModel workflowParametersPresentationModel;

        /// <summary>
        /// Initializes a new instance of the MonitorModule class
        /// </summary>
        /// <param name="container">instance of the Unity container</param>
        /// <param name="regionManager">instance of the region manager</param>
        public MonitorModule(IUnityContainer container, IRegionManager regionManager)
        {
            this.container = container;
            this.regionManager = regionManager;
        }

        /// <summary>
        /// Initializes the modules and registers views to the trident main window
        /// </summary>
        public void Initialize()
        {
            this.executionVisualizerPresentationModel = this.container.Resolve<ExecutionVisualizerPresentationModel>();

            this.RegisterViewsAndServices();

            this.executionVisualizerPresentationModel.Initialize();
            this.dataProductPresentationModel = this.container.Resolve<DataProductPresentationModel>();
            this.processingStatusPresentationModel = this.container.Resolve<ProcessingStatusPresentationModel>();
            this.inputOutputPresentationModel = this.container.Resolve<InputOutputPresentationModel>();
            this.performancePresentationModel = this.container.Resolve<PerformancePresentationModel>();
            this.workflowParametersPresentationModel = new WorkflowParametersPresentationModel(this.container, new WorkflowParametersView(), this.container.Resolve<JobCommandProxy>());
            this.container.RegisterInstance<WorkflowParametersPresentationModel>("monitorWorkflowParamsPresentationModel", this.workflowParametersPresentationModel);

            this.monitorSettingsWindow = container.Resolve<MonitorSettingsWindow>();
            RibbonCommands.MonitorSettingsCommand.RegisterCommand(new DelegateCommand<object>(p =>
            {
                this.monitorSettingsWindow = container.Resolve<MonitorSettingsWindow>();
                this.monitorSettingsWindow.ShowDialog();
            }));

            this.regionManager.Add(dataProductPresentationModel.View, "IntermediateResultsRegion");
            this.regionManager.Add(processingStatusPresentationModel.View, "ProcessingStatusRegion");
            this.regionManager.Add(inputOutputPresentationModel.View, "InputOutputRegion");
            this.regionManager.Add(performancePresentationModel.View, "PerformanceRegion");
            this.regionManager.Add(this.workflowParametersPresentationModel.View, "WorkflowParametersRegion");
        }

        /// <summary>
        /// Registers the views and services to the Unity container
        /// </summary>
        private void RegisterViewsAndServices()
        {
            try
            {
                this.monitorSettingService = this.container.Resolve<MonitorSettingService>();
                this.container.RegisterInstance<MonitorSettingService>(this.monitorSettingService, new ExternallyControlledLifetimeManager());

                this.dataProductService = this.container.Resolve<DataProductService>();
                this.container.RegisterInstance<IDataProductService>(this.dataProductService, new ExternallyControlledLifetimeManager());
                string attempts = ConfigurationManager.AppSettings["RegistryReconnectAttempts"];
                if (!string.IsNullOrEmpty(attempts))
                {
                    int attemptsInt = 0;
                    bool success = int.TryParse(attempts, out attemptsInt);
                    if (success)
                    {
                        this.dataProductService.MaxRegistryConnectionAttempts = attemptsInt;
                    }
                }

                this.monitorService = this.container.Resolve<MonitorService>();

                this.container.RegisterInstance<IMonitorService>(this.monitorService, new ExternallyControlledLifetimeManager());

                this.monitorLoggingService = this.container.Resolve<MonitorLoggingService>();
            }
            catch (ResolutionFailedException ex)
            {
                throw;
            }
        }
    }
}
